import { SetupContext, computed, defineComponent, ref } from 'vue';
import { CalendarPropsType, calendarProps } from './calendar.props';
import useCalendar from './composition/use-calendar';
import { useDate } from './composition/use-date';
import { DayInCalendar } from './types/calendar';
import { useCompare } from './composition/use-compare';
import { DateObject, weekDays } from './types/common';
import { ScheduleEvent } from './types/schedule';
import { defaultNameOfMonths } from './types/month';

export default defineComponent({
    name: 'FCalendar',
    props: calendarProps,
    emits: [],
    setup(props: CalendarPropsType, context: SetupContext) {
        const { sameDay } = useCompare();
        const { getToday } = useDate();
        const firstDayOfTheWeek = ref(props.firstDayOfTheWeek);
        const events = ref<ScheduleEvent[]>(props.events);
        const today = getToday();
        const activeDay = ref<DateObject>({
            year: today.year || 1,
            month: today.month || 1,
            day: today.day || 1
        });
        const activeView = ref<number>(3);

        const {
            getMonthlyCalendar,
            getWeeklyCalendar,
            getPreviousDay,
            getNextDay,
            getDayInPreviousWeek,
            getDayInNextWeek,
            getDayInPreviousMonth,
            getDayInNextMonth
        } = useCalendar();

        const title = computed(() => {
            return `${defaultNameOfMonths[activeDay.value.month || 1]} ${activeDay.value.year}`;
        });

        const dates = computed(() => {
            const weekItems = getMonthlyCalendar(activeDay.value.month || 1, activeDay.value.year || 1, firstDayOfTheWeek.value);
            return weekItems;
        });

        const week = computed(() => {
            const weekItem = getWeeklyCalendar(
                activeDay.value.day || 1,
                activeDay.value.month || 1,
                activeDay.value.year || 1,
                firstDayOfTheWeek.value
            );
            return weekItem;
        });

        const day = computed(() => {
            return week.value.days.find((day: DayInCalendar) => sameDay(day.date, activeDay.value)) || week.value.days[1];
        });

        const dayInWeek = computed(() => {
            const matchedIndex = week.value.days.findIndex((day: DayInCalendar) => sameDay(day.date, activeDay.value));
            const dayIndexInWeek = matchedIndex > -1 ? matchedIndex : 1;
            return weekDays[dayIndexInWeek];
        });

        const shouldShowMonthlyView = computed(() => {
            return activeView.value === 3;
        });

        const shouldShowWeeklyView = computed(() => {
            return activeView.value === 2;
        });

        const shouldShowDailyView = computed(() => {
            return activeView.value === 1;
        });

        function changeActiveView(viewIndex: number) {
            activeView.value = viewIndex;
        }

        function previous(viewIndex: number) {
            if (viewIndex === 1) {
                activeDay.value = getPreviousDay(activeDay.value);
            }
            if (viewIndex === 2) {
                activeDay.value = getDayInPreviousWeek(activeDay.value);
            }
            if (viewIndex === 3) {
                activeDay.value = getDayInPreviousMonth(activeDay.value);
            }
        }

        function next(viewIndex: number) {
            if (viewIndex === 1) {
                activeDay.value = getNextDay(activeDay.value);
            }
            if (viewIndex === 2) {
                activeDay.value = getDayInNextWeek(activeDay.value);
            }
            if (viewIndex === 3) {
                activeDay.value = getDayInNextMonth(activeDay.value);
            }
        }

        function resetToToday() {
            activeDay.value = {
                year: today.year || 1,
                month: today.month || 1,
                day: today.day || 1
            };
        }

        return () => {
            return (
                <div class="f-calendar">
                    <f-calendar-header
                        activeView={activeView.value}
                        title={title.value}
                        onViewChange={(viewIndex: number) => changeActiveView(viewIndex)}
                        onPrevious={(viewIndex: number) => previous(viewIndex)}
                        onNext={(viewIndex: number) => next(viewIndex)}
                        onResetToToday={() => resetToToday()}></f-calendar-header>
                    <div>
                        {shouldShowDailyView.value && (
                            <f-calendar-day-view day={day.value} dayInWeek={dayInWeek.value} events={events.value}></f-calendar-day-view>
                        )}
                        {shouldShowWeeklyView.value && (
                            <f-calendar-week-view week={week.value} events={events.value}></f-calendar-week-view>
                        )}
                        {shouldShowMonthlyView.value && (
                            <f-calendar-month-view
                                activeDay={activeDay.value}
                                dates={dates.value}
                                events={events.value}></f-calendar-month-view>
                        )}
                    </div>
                </div>
            );
        };
    }
});
